//
//  ES1Renderer.m
//  IRayTracer
//
//  Created by Prashant on 21/06/10.
//  Copyright Sourcebits Technologies 2010. All rights reserved.
//

#import "ES1Renderer.h"
#include "Scene.h"
#include "Shapes.h"

 GLuint texid;
 Scene* scene = 0;
 Sphere* sphere = 0;
 Light* light = 0;
 Light* light1 = 0;
 
 void initTexture(unsigned char* data)
 {	 
 glEnable (GL_TEXTURE_2D); 
 glGenTextures( 1 , &texid);
 glBindTexture(GL_TEXTURE_2D , texid);
 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexImage2D(GL_TEXTURE_2D , 0 , GL_RGBA , scene->getWidth() , scene->getHeight() , 0 , GL_RGBA , GL_UNSIGNED_BYTE, data);
	 printf("error =%d",glGetError());
 }
 
 
 @implementation ES1Renderer

// Create an OpenGL ES 1.1 context
- (id)init
{
    if ((self = [super init]))
    {
        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

        if (!context || ![EAGLContext setCurrentContext:context])
        {
            [self release];
            return nil;
        }

        // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
        glGenFramebuffersOES(1, &defaultFramebuffer);
        glGenRenderbuffersOES(1, &colorRenderbuffer);
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
    }
	
	sphere = new Sphere(85.0f);
	light  = new Light();
	scene = new Scene(512 , 512 );
	scene->addLights(light);
	scene->addObjects(sphere);
	
	scene->startRayTracing();
	initTexture(scene->getImageData());
	
    return self;
}

- (void)render
{
    // Replace the implementation of this method to do your own custom drawing

    static const GLfloat squareVertices[] = {
        -0.5f,  -0.5f,
         0.5f,  -0.5f,
         0.5f,   0.5f,
		-0.5f,   -0.5f,
		 0.5f,   0.5f,
		-0.5f,   0.5f,
		
    };

    static const GLubyte squareColors[] = {
        255, 255,   0, 255,
        0,   255, 255, 255,
        0,     0,   0,   0,
        255,   0, 255, 255,
    };
	
	static const GLfloat squareTexCoord[] = {
        0.0f,  0.0f,
		1.0f,  0.0f,
        1.0f,   1.0f,
		0.0f,   0.0f,
		1.0f,   1.0f,
		0.0f,   1.0f,
    };

    static float transY = 0.0f;
	// This application only creates a single context which is already set current at this point.
    // This call is redundant, but needed if dealing with multiple contexts.
    [EAGLContext setCurrentContext:context];

    // This application only creates a single default framebuffer which is already bound at this point.
    // This call is redundant, but needed if dealing with multiple framebuffers.
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
    glViewport(0, 0, backingWidth, backingHeight);
	Matrix4f perspective , lookAtMatrix;
	perspective.perspective(M_PI/3.0f,320.0f/480, 0.001f, 100.0f);
	Point3 eye; eye.x = 0.0f;eye.y = 0.0f ; eye.z = -1.0f;
	Point3 target; target.x = 0.0f ; target.y = 0.0f ; target.z = 0.0f;
	Vector3 up; up.x = 0.0f ; up.y = 1.0f; up.z = 0.0f;
	lookAtMatrix.lookAt(eye, target, up);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
	glLoadMatrixf(perspective.pointer());
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
	glLoadMatrixf(lookAtMatrix.pointer());
    //glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f);
    //transY += 0.075f;
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glVertexPointer(2, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    //glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
    //glEnableClientState(GL_COLOR_ARRAY);
	glTexCoordPointer(2, GL_FLOAT, 0, squareTexCoord);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glDrawArrays(GL_TRIANGLES, 0, 6);
	
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);


    // This application only creates a single color renderbuffer which is already bound at this point.
    // This call is redundant, but needed if dealing with multiple renderbuffers.
    //glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer
{	
    // Allocate color buffer backing based on the current layer size
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
    {
        NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
        return NO;
    }

    return YES;
}

- (void)dealloc
{
    // Tear down GL
    if (defaultFramebuffer)
    {
        glDeleteFramebuffersOES(1, &defaultFramebuffer);
        defaultFramebuffer = 0;
    }

    if (colorRenderbuffer)
    {
        glDeleteRenderbuffersOES(1, &colorRenderbuffer);
        colorRenderbuffer = 0;
    }

    // Tear down context
    if ([EAGLContext currentContext] == context)
        [EAGLContext setCurrentContext:nil];

    [context release];
    context = nil;

    [super dealloc];
}

@end
